<template>
  <div class="city-wrapper bgc-base" ref="listWrapper">
    <section class="search-wrapper">
      <div :class="{'focused': isSearchInputFocused}">
        <div class="focused-layer" @click="isSearchInputFocused = false"></div>
        <div class="search-box-wrap">
          <div class="search-box">
            <div class="search-inner fx fx-align-center">
              <span class="search-icon"></span>
              <input class="fx-1 bgc-t mr-12 search-input"
                    @focus="isSearchInputFocused = true"
                    v-model="keyWords"
                    type="text" placeholder="请输入城市名或者拼音">
            </div>
          </div>
          <div class="pl-16 bgc-f">
            <div class="" v-show="isSearchInputFocused && searchResult.length">
              <div class="result-cell bd-b fx" v-for="item in searchResult"
                  :key="item.city_id"
                  @click="chooseCity(item)">{{item.name}}</div>
            </div>
            <div class="result-cell bd-b fx" v-show="keyWords && noResult">抱歉，未找到相关城市，请尝试修改</div>
          </div>
        </div>
      </div>
    </section>
    <section>
      <div class="list-unit">
        <div class="unit-head-wrap" :ref="0">
          <div class="unit-head bgc-base"
                :class="{'pos-f': currentSection == 0}"
          >当前城市</div>
        </div>
        <div class="unit-body click--active-grey">
          <div class="pt-12 pb-12 bd-b c-2 f-16"
                @click.stop="chooseCity(currentCity)"
                v-if="currentCity.name">{{currentCity.name}}</div>
          <div class="pt-12 pb-12 bd-b c-9 f-16" v-else>定位失败</div>
        </div>
      </div>
      <div class="list-unit" v-for="(cities, idx) in cityList" :key="idx">
        <div class="unit-head-wrap" :ref="cities[0].category_id">
          <div class="unit-head bgc-base"
              :class="{'pos-f': currentSection == cities[0].category_id}"
          >{{cities[0].category_id}}
          </div>
        </div>
        <div class="unit-body click--active-grey"
              v-for="city in cities" :key="city.city_id"
              @click="chooseCity(city)">
          <div class="pt-12 pb-12 bd-b c-2 f-16">{{city.name}}</div>
        </div>
      </div>
    </section>
    <section class="alpha-nav">
      <div class="alpha-words" v-for="(word, index) in alphabet"
            :key="index" @click="handleWordClick(word, index)">{{word}}</div>
    </section>
    <transition name="fade">
      <section class="popup-word fx fx-align-center fx-justify-center" v-if="isShowBigWord">{{currentWord}}</section>
    </transition>
  </div>
</template>

<script>
  import '../assets/css/base.css';
  import { throttle } from '../assets/libs/utils.js'

  export default {
    props: [
      'cityListRaw', // 城市列表
      'currentCityId', // 当前城市id
    ],

    data () {
      return {
        alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
        currentSection: -1, // 当前所在城市分类 -1为不在任何分类，0当前城市， A-Z代表城市类别
        isShowBigWord: false, // 是否显示word的toast
        currentWord: '', // 当前点击城市分类
        currentCity: {}, // 当前所在城市
        cityList: [], // 格式化过的城市列表
        searchedCityRes: [], // 搜索到的城市列表
        isSearchInputFocused: false, // 是否搜索框聚焦
        keyWords: '', // 搜索词汇
        searchResult: [], // 搜索城市结果
        noResult: false, // 无匹配结果
      }
    },

    created () {
      this.getCityData()
    },

    mounted: function () {
      // 对scroll事件做节流处理
      this.throttledScroll = throttle(this.computeScroll, 20)
      this.$refs.listWrapper.addEventListener('scroll', this.handleScroll)
    },

    beforeDestroy: function () {
      this.$refs.listWrapper.removeEventListener('scroll', this.handleScroll)
    },

    watch: {
      // 搜索城市
      keyWords: function(newV, oldV) {
        var _this = this;
        clearTimeout(this.timer);
        this.noResult = false;
        this.timer = setTimeout(function() {
          _this.filterCity(newV);
        }, 500);
      }
    },

    methods: {
      // 获取城市信息
      getCityData: function () {
        this.cityList = this.cityListRaw ? this.processCityList(this.cityListRaw) : [];
        var alphabet = '';
        this.cityListRaw.forEach((val, idx) => {
          var firstLetter = val.name_en.substring(0, 1);
          firstLetter = firstLetter.toUpperCase();
          if (alphabet.indexOf(firstLetter) === -1) alphabet += firstLetter;
          if (val.city_id == this.currentCityId) {
            this.currentCity = val;
          }
        })
        this.alphabet = alphabet;
      },

      // 绑定的scroll事件
      handleScroll: function(e) {
        this.throttledScroll(e)
      },
      
      /**
       * 处理页面滚动事件
       * @param e {{obj}} 事件
       * @return null
      */
      computeScroll: function(e) {
        if (!this.$refs.listWrapper) return;
        var scrollTop = this.$refs.listWrapper.scrollTop;
        var refs = this.$refs;
        var cityList = this.cityList;

        var firstChar;
        var firstCategoryChar;
        var nextCategoryChar;

        // 对于v-for获得的ref是一个数组，所以以下会出现类似refs[key][0]这种写法
        // lastCategoryChar 格式化过的城市列表最后一个类别(如类别Z)
        var lastCategoryChar = cityList[cityList.length - 1][0].category_id;
        for (var i = 0, len = cityList.length; i < len; i++) {
          // firstChar 是每个城市拼音首字母，代表所在类别
          // firstCategoryChar 格式化过的城市列表第一个类别(如类别A)
          // nextCategoryChar 是遍历到当前类别的下一个类别
          firstChar = cityList[i][0].category_id;
          firstCategoryChar = cityList[0][0].category_id;
          nextCategoryChar = cityList.length > i + 1 ? cityList[i + 1][0].category_id : '';
          if (refs[0] && scrollTop < refs[0].offsetTop) { // 不在任何类别
            this.currentSection = -1;
            break;
          } else if (
            refs[0] && scrollTop >= refs[0].offsetTop &&
            scrollTop < refs[firstCategoryChar][0].offsetTop
          ) { // 在当前城市栏
            this.currentSection = 0;
            break;
          } else if (
            i < cityList.length - 1 &&
              scrollTop >= refs[firstChar][0].offsetTop &&
              scrollTop < (refs[nextCategoryChar] && refs[nextCategoryChar][0].offsetTop)
          ) { // 滚动到两个城市的区间
            this.currentSection = firstChar;
            break;
          } else if (scrollTop >= refs[lastCategoryChar][0].offsetTop) { // 在最后一个城市
            this.currentSection = lastCategoryChar;
            break;
          }
        }
      },
      
      // 处理点击字母列表
      handleWordClick: function(word, index) {
        var _this = this;
        this.currentWord = word;
        this.isShowBigWord = true;
        // 如果没有该分类，回到顶部
        var scrollTop = this.$refs[word] && this.$refs[word][0].offsetTop;
        // 兼容scrollTop不同浏览器的表现
        this.$refs.listWrapper.scrollTop = scrollTop;
        clearTimeout(this.timer);
        this.timer = setTimeout(function() {
          _this.isShowBigWord = false;
        }, 1500);
      },

      /**
       * 格式化城市列表数据
       * @param cities {{array}} 城市列表rawdata
       * @param cityName {{string}} 通过该字段查询对应城市信息
       * @return newCityList {{array}} 如果没有查询城市，就返回格式化的城市列表
       *  || resultData {{obj}} 如果有查询城市，返回。属性newCityList：格式化过的城市列表；属性ipLocationCity: 定位城市
       */
      processCityList: function(cities, cityName) {
        var formatedCityList = {};
        var resultData = {};
        var newCityList = [];
        var ipLocationCity = '';
        var firstChar
        cities.sort(function(a, b) {
          return a.name_en.charCodeAt(0) - b.name_en.charCodeAt(0)
        });
        for (var idx = 0, len = cities.length; idx < len; idx++) {
          firstChar = cities[idx].name_en.charAt(0).toUpperCase();
          cities[idx].category_id = firstChar;
          if (formatedCityList[firstChar]) {
            formatedCityList[firstChar].push(cities[idx]);
          } else {
            formatedCityList[firstChar] = [cities[idx]];
          }
          // 通过城市名称查询定位的城市信息
          if (cityName && cityName.indexOf(cities[idx].name) !== -1) {
            ipLocationCity = cities[idx];
            resultData.ipLocationCity = ipLocationCity;
          }
        }
        // 城市列表格式从对象转换成数组
        for (var key in formatedCityList) {
          newCityList.push(formatedCityList[key]);
        }

        if (!cityName) {
          return newCityList;
        } else {
          resultData.newCityList = newCityList;
          return resultData;
        }
      },

      // 筛选与搜索匹配的城市
      filterCity: function(searchName) {
        if (searchName) {
          this.searchResult = this.cityListRaw.filter(function (val) {
            return val.name.indexOf(searchName) !== -1
          });
          this.noResult = this.searchResult.length == 0;
        } else {
          this.noResult = true;
          this.searchResult = [];
        }
      },

      // 选择城市 @param city {{Object}} 城市信息
      // 处理路由及选中城市的信息
      chooseCity: function(city) {
        this.$emit('chooseCity', city);
      }
    }
  }
</script>

<style lang="scss" scoped>

.city-wrapper {
  overflow-x: hidden;
  user-select: none;
  position: fixed;
  left: 0;
  top: 0;
  z-index: 999;
  width: 100%;
  height: 100%;
  line-height: 1.5;
  overflow-y: scroll;
  -webkit-overflow-scrolling: touch;
}
.search-wrapper {
  position: relative;
  height: 48px;
}
.focused {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 999;
  width: 100%;
}
.focused-layer {
  display: none;
}
.focused .focused-layer {
  display: block;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1000;
  width: 100%;
  height: 100%;
  background: rgba(0,0,0,.5);
}
.search-box {
  box-sizing: border-box;
  width: 100%;
  padding: 8px 24px;
  background:rgba(255,255,255,1);
  box-shadow: 0px 1px 0px 0px rgba(229,229,229,1); 
}
.search-box .search-inner {
  width: 100%;
  height: 32px;
  border-radius: 32px;
  background:rgba(242,243,244,1);
}
.search-icon {
  margin: 0 8px 0 82px;
  width: 16px;
  height: 16px;
  background: url() no-repeat center center/contain;
}
.result-cell {
  font-size: 16px;
  height: 48px;
  line-height: 48px;
  background: #fff;
}
.focused .search-box-wrap {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1100;
  width: 100%;
}

.alpha-nav {
  position: fixed;
  top: 62px;
  right: 0px;
  width: 28px;
  z-index: 999;
  color: rgba(0,0,0,0.38);
}
.alpha-words {
  text-align: center;
  line-height: 16px;
}

.unit-head-wrap {
  position: relative;
  height: 32px;
}
.unit-head {
  top: 0;
  left: 0;
  z-index: 999;
  padding: 8px 16px;
  width: 100%;
  line-height: 16px;
  color: rgba(0,0,0,0.38);
}
.unit-body {
  padding: 0 16px;
  background: #fff;
}

.popup-word {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  z-index: 999;
  margin: auto;
  width:144px;
  height:144px; 
  background:rgba(66,68,86,1);
  border-radius: 10px ; 
  font-size: 76px;
  color: #fff;
}

.reset-pos-0 {
  top: 0;
  left: 0;
}
.fade-enter-active, .fade-leave-active {
  transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
}
</style>